package com.ds.lens.flink.monitor.common.bo;

import com.ds.lens.data.common.constant.AggregatorEnum;
import com.ds.lens.data.common.document.DataPoint;
import com.ds.lens.data.common.document.dto.MonitorKey;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.io.Serializable;
import java.util.*;

@Getter
@ToString
public class Metric implements Serializable {
    private static final long serialVersionUID = 1581511683093409303L;
    private String uid;
    private MonitorKey monitorKey;
    private String metricName;
    private AggregatorEnum aggrMethod;
    @Setter
    private Map<String, Object> groupBys;
    @Setter
    private List<DataPoint> values;
    @Setter
    private Long startTime;
    @Setter
    private Long endTime;

    public Metric(MonitorKey monitorKey, String metricName, AggregatorEnum aggrMethod) {
        this.uid = UUID.randomUUID().toString();
        this.monitorKey = monitorKey;
        this.metricName = metricName;
        this.aggrMethod = aggrMethod;
    }

    public void addGroupByField(String name, Object value) {
        if (groupBys == null) {
            groupBys = new HashMap<>();
        }
        groupBys.put(name, value);
    }

    public void addMetricValue(DataPoint value) {
        if (values == null) {
            values = new ArrayList<>();
        }
        values.add(value);
    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof Metric) {
            Metric otherMetric = ((Metric)other);
            boolean f = this.monitorKey.getMonitorId().equals(otherMetric.getMonitorKey().getMonitorId()) &&
                    this.monitorKey.getVersion().equals(otherMetric.getMonitorKey().getVersion()) &&
                    this.metricName.equalsIgnoreCase(otherMetric.metricName) &&
                    this.aggrMethod.equals(otherMetric.aggrMethod) &&
                    this.startTime.equals(otherMetric.startTime) &&
                    this.endTime.equals(otherMetric.endTime);
            if (!f) {
                return false;
            }
            if (this.groupBys == null && otherMetric.groupBys != null ||
                    this.groupBys != null && otherMetric.groupBys == null) {
                return false;
            } else if (this.groupBys != null && otherMetric.groupBys != null) {
                if (this.groupBys.size() != otherMetric.groupBys.size()) {
                    return false;
                }
                for (String thisKey : this.groupBys.keySet()) {
                    Object thisValue = this.groupBys.get(thisKey);
                    Object otherValue = otherMetric.groupBys.get(thisKey);
                    if (!Objects.deepEquals(thisValue, otherValue)) {
                        return false;
                    }
                }
            }
            return true;
        } else {
            return false;
        }
    }
}
